package ch.fhnw.qualiscan.application.views;

import ch.fhnw.qualiscan.Config;
import ch.fhnw.qualiscan.application.controllers.AdminQuestionnaire;
import ch.fhnw.qualiscan.application.elements.AdminQuestionForm;
import ch.fhnw.qualiscan.application.modals.AdminDeleteDomain;
import ch.fhnw.qualiscan.application.modals.AdminEditDomain;
import ch.fhnw.qualiscan.application.modals.AdminNewDomain;
import ch.fhnw.qualiscan.application.modals.AdminNewQuestion;
import ch.fhnw.qualiscan.core.View;
import ch.fhnw.qualiscan.core.db.helpers.adminDomainTableArgs;
import ch.fhnw.qualiscan.core.db.pojos.Domain;
import ch.fhnw.qualiscan.core.db.pojos.Question;
import ch.fhnw.qualiscan.core.db.pojos.Questionnaire;
import ch.fhnw.qualiscan.core.libraries.LanguageLibrary;
import ch.fhnw.qualiscan.core.libraries.NotificationLibrary;

import java.util.Iterator;

import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Form;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.BaseTheme;

import eu.livotov.tpt.i18n.TM;

/**
 * Once selected a questionnaire, this view shows the UI components for selecting/adding domains and adding/editing questions.
 * @author bengro
 */
public class AdminQuestionnaireView extends View {

    AdminQuestionnaire controller;
    AdminQuestionnaireView view;
    
    private VerticalLayout adminWrap;
    private Label title;

    VerticalLayout editQuestionnaireWrap;
    VerticalLayout editDomainsWrap;
    VerticalLayout editQuestionsWrap;
    
    private Panel p1;
    private Panel p2;
    
    // are used by models, need to be accessible by other classes.
    private Domain currentDomain;
    private NativeSelect domainSelect;
    private BeanItemContainer<adminDomainTableArgs> domainsTableContainer;
    private Table domainTable;
    
    
    private HorizontalLayout questionSelect;
    private HorizontalLayout domainSwitcher;
    
    private CssLayout noDomainsBox;
    
    public AdminQuestionnaireView(AdminQuestionnaire controller) {
        this.controller = controller;
        this.view = this;
    }

    @Override
    public void initComponents() {

    }

    @Override
    public void buildLayout() {
        removeAllComponents();
        questionSelect = new HorizontalLayout();

        adminWrap = new VerticalLayout();
	adminWrap.setMargin(true, true, true, true);
	adminWrap.setSpacing(true);

	title = textHelper.h1(TM.get("admin.questionnaire.title"));
	adminWrap.addComponent(title);
        
        // is this questionnaire used in production?
        int surveysCount = controller.getSurveyModel().isSurveyByQuestionnaire(controller.getCurrentQuestionnaire());
        if(surveysCount != 0) {
            adminWrap.addComponent(textHelper.span(TM.get("admin.questionnaire.production", surveysCount)));
        } else {
            adminWrap.addComponent(textHelper.span(TM.get("admin.questionnaire.noproduction")));
        }
        
        // Button w/ text, icon and tooltip
        Button b = new Button(TM.get("action.back"));
        b.setStyleName(BaseTheme.BUTTON_LINK);
        
        b.setIcon(Config.ICON_BACK);
        b.addListener(new Button.ClickListener() {
        	public void buttonClick(ClickEvent arg0) {
				// TODO Auto-generated method stub
				controller.backToPanel();
			}
        }); 
        adminWrap.addComponent(b);

        adminWrap.addComponent(editQuestionnaire());
        
        VerticalLayout spacer1 = new VerticalLayout();
        spacer1.setHeight(25, UNITS_PIXELS);
        adminWrap.addComponent(spacer1);
        
        adminWrap.addComponent(textHelper.h2(TM.get("admin.questionnaire.editdomains")));
        adminWrap.addComponent(loadEditDomains());

        VerticalLayout spacer2 = new VerticalLayout();
        spacer2.setHeight(25, UNITS_PIXELS);
        adminWrap.addComponent(spacer2);
     
        adminWrap.addComponent(loadEditQuestions());
        
        addComponent(adminWrap);
    }

    /**
     * Edit Questionnaire part where title, description and state can be modified.
     * @return 
     */
    public VerticalLayout editQuestionnaire() {
        this.editQuestionnaireWrap = new VerticalLayout();

        final Form questionnaireForm = new Form();
        questionnaireForm.setCaption(null);
        
        HorizontalLayout buttonBar = new HorizontalLayout();
        questionnaireForm.getFooter().addComponent(buttonBar);

        TextField titleField = new TextField(); 
        titleField.setColumns(20);
        titleField.setWidth("400px");
        titleField.isRequired();
        titleField.setCaption(TM.get("admin.questionnaire.add.title"));
        titleField.setValue(controller.getCurrentQuestionnaire().getTitle());
        questionnaireForm.addField("titleField", titleField);

        TextArea descField = new TextArea();
        descField.setColumns(20);
        descField.setRows(3);
        descField.setCaption(TM.get("admin.questionnaire.add.desc"));
        descField.setValue(controller.getCurrentQuestionnaire().getDescription());
        questionnaireForm.addField("descField", descField);

        CheckBox cb = new CheckBox();
        cb.setDescription(TM.get("admin.questionnaire.activation"));
        cb.setCaption(TM.get("admin.questionnaire.activate"));
        cb.setImmediate(true);
        if(controller.getCurrentQuestionnaire().getActive() == 1) {
            cb.setValue(true);
        }
        questionnaireForm.addField("activateField", cb);
        
        Button saveButton = new Button(TM.get("action.save"), new Button.ClickListener() {
            public void buttonClick(Button.ClickEvent event) {
                questionnaireForm.commit();
                String title = (String) questionnaireForm.getField("titleField").getValue();
                String desc = (String) questionnaireForm.getField("descField").getValue();
                Boolean activated = (Boolean) questionnaireForm.getField("activateField").getValue();
                
                Questionnaire questionnaire = controller.getCurrentQuestionnaire();
                questionnaire.setTitle(title);
                questionnaire.setDescription(desc);
                
                if(activated) {
                    questionnaire.setActive(1);
                } else {
                    questionnaire.setActive(0);
                }
                
                if(!title.equals("")) {
                    controller.getqModel().updateQuestionnaire(questionnaire);
                    getWindow().showNotification(TM.get("admin.questionnaire.updated"));
                } else {
                    getWindow().showNotification(TM.get("admin.questionnaire.notupdated"));
                }
            }
        });

        saveButton.setData(this);
        saveButton.setIcon(Config.ICON_SAVE);
        buttonBar.addComponent(saveButton);
        
        editQuestionnaireWrap.addComponent(questionnaireForm);
        
        return editQuestionnaireWrap;
    }
    
    /**
     * responsible for loading the edit domain section.
     * @return
     */
    public VerticalLayout loadEditDomains() {
        this.editDomainsWrap = new VerticalLayout();
        domainsTableContainer = controller.loadDomains();
        
        HorizontalLayout addDomainForm = new HorizontalLayout();
        addDomainForm.setMargin(false, false, true, false);

        Button addButton =  new Button(TM.get("action.add"), new Button.ClickListener() {
                public void buttonClick(Button.ClickEvent event) {
                    openModal(new AdminNewDomain(controller.loadDomains(), view));
                }
        });
        addButton.setIcon(Config.ICON_ADD);
        addDomainForm.addComponent(addButton);
        editDomainsWrap.addComponent(addDomainForm);
        

        domainTable = new Table();
        domainTable.setWidth("100%");
        domainTable.setPageLength(0);
        domainTable.setSelectable(true);
        domainTable.setImmediate(true);
        
        domainTable.addGeneratedColumn("domainEditButton", new Table.ColumnGenerator() {
            public Component generateCell(Table source, Object itemId, Object columnId) {

                Button editButton = new Button(TM.get("action.edit"), new Button.ClickListener() {
                        public void buttonClick(Button.ClickEvent event) {
                                adminDomainTableArgs adta = (adminDomainTableArgs) event.getButton().getData();
                                openModal(new AdminEditDomain(adta, view));
                        }
                });
                editButton.setData(itemId);
                editButton.setIcon(Config.ICON_EDIT);
                return editButton;
            }
        });

        domainTable.addGeneratedColumn("domainDeleteButton", new Table.ColumnGenerator() {
            public Component generateCell(Table source, Object itemId, Object columnId) {

                Button deleteButton = new Button(TM.get("action.delete"), new Button.ClickListener() {
                        public void buttonClick(Button.ClickEvent event) {
                                adminDomainTableArgs adta = (adminDomainTableArgs) event.getButton().getData();
                                openModal(new AdminDeleteDomain(adta, view));
                        }
                });
                deleteButton.setData(itemId);
                deleteButton.setIcon(Config.ICON_CANCEL);

                return deleteButton;
            }
        });

        domainTable.setContainerDataSource(getDomainsTableContainer());
        
        domainTable.setColumnHeader("titleEng", TM.get("admin.domaintable.engtitle"));
        domainTable.setColumnHeader("numberQuestions", TM.get("admin.domaintable.numberquestions"));
        domainTable.setColumnHeader("domainEditButton", TM.get("action.edit"));
        domainTable.setColumnHeader("domainDeleteButton", TM.get("action.delete"));
        domainTable.setVisibleColumns(new Object[]{"titleEng", "numberQuestions", "domainEditButton", "domainDeleteButton"});
        
        noDomainsBox = new CssLayout();
        noDomainsBox.setVisible(true);
        noDomainsBox.setMargin(true);
        noDomainsBox.setWidth("800px");
        noDomainsBox.setStyleName("box-warning");
        noDomainsBox.addComponent(textHelper.p(TM.get("admin.questionnaire.nodomains")));
        
        editDomainsWrap.addComponent(noDomainsBox); 
        editDomainsWrap.addComponent(domainTable);
        
        if(getDomainsTableContainer().size() == 0) {
            domainTable.setVisible(false);
            noDomainsBox.setVisible(true);
        } else {
            domainTable.setVisible(true);
            noDomainsBox.setVisible(false);
        }
        
        return editDomainsWrap;
    }
    
    /**
     * Responsible for loading the question edit interface.
     * @return 
     */
    public VerticalLayout loadEditQuestions() {
        this.editQuestionsWrap = new VerticalLayout();
        editQuestionsWrap.addComponent(textHelper.h2(TM.get("admin.questionnaire.editquestions")));
        
        p1 = new Panel();
	p2 = new Panel();
        
        questionSelect.addComponent(displayForm());
       
        p1.addComponent(questionSelect);
        
        this.editQuestionsWrap.addComponent(p1);
        
        if(getDomainsTableContainer().size() == 0) {
            editQuestionsWrap.setVisible(false);
        } else {
            editQuestionsWrap.setVisible(true);
        }
        
        return editQuestionsWrap;
    }

    public HorizontalLayout displayForm() {
        domainSwitcher = new HorizontalLayout();
        domainSwitcher.setSpacing(true);
        domainSwitcher.setMargin(true);

        // get native select from controller.
        domainSelect = controller.getDomainSelect();
        domainSwitcher.addComponent(getDomainSelect());

        // button
        Button switchButton = new Button(TM.get("admin.tab2.selectbutton"));
        switchButton.addListener(new Button.ClickListener() {
                public void buttonClick(Button.ClickEvent event) {
                    if(getDomainSelect().getValue() != null)
                        displayQuestions(getDomainSelect().getValue());
                }
        });

        domainSwitcher.addComponent(switchButton);
        return domainSwitcher;
    }

    public void displayQuestions(Object value) {

        p2.removeAllComponents();
        p2.addComponent(addQuestion());
        p2.setVisible(true);

        currentDomain = controller.getDomainModel().getDomainById(Integer.parseInt((String) value.toString()));
        
        if(currentDomain != null) {
                this.editQuestionsWrap.addComponent(p2);

                Iterator<Question> questionIterator = currentDomain.getQuestions().iterator();

                int counter = 0;
                int subCounter = 0;
                while (questionIterator.hasNext()) {

                        subCounter = 0;
                        counter++;
                        Question currentQuestion = (Question) questionIterator.next();
                        String currentQuestionText = controller.getQuestionModel().getQuestionText(new LanguageLibrary().getDefaultLanguage(),currentQuestion).getText();

                        if(currentQuestion.getSubquestions().size() > 0) {

                                AdminQuestionForm wSubquestionContainer = new AdminQuestionForm(currentQuestion, counter, new LanguageLibrary().getDefaultLanguage(), false, this);
                                p2.addComponent(wSubquestionContainer);

                                //Question has subquestions
                                Iterator subQuestionIterator = currentQuestion.getSubquestions().iterator();
                                while(subQuestionIterator.hasNext()) {
                                        subCounter++;
                                        Question currentSubQuestion = (Question) subQuestionIterator.next();
                                        String currentSubQuestionText = controller.getQuestionModel().getQuestionText(new LanguageLibrary().getDefaultLanguage(),currentSubQuestion).getText();

                                        AdminQuestionForm questionContainer = new AdminQuestionForm(currentSubQuestion, subCounter, new LanguageLibrary().getDefaultLanguage(), true, this);
                                        p2.addComponent(questionContainer);
                                }
                        }
                        else {
                                //Question has no subquestion
                                AdminQuestionForm questionContainer = new AdminQuestionForm(currentQuestion, counter, new LanguageLibrary().getDefaultLanguage(), false, this);
                                p2.addComponent(questionContainer);
                        }
                }

        } else {
                NotificationLibrary.showError(TM.get("error"), TM.get("error.standard"));
        }
    }

    public HorizontalLayout addQuestion() {
        HorizontalLayout addQuestionWrap = new HorizontalLayout();
        addQuestionWrap.setMargin(true, true, true, false);

        Button addQuestionButton = new Button(TM.get("action.new"));
        addQuestionButton.addListener(new Button.ClickListener() {
            public void buttonClick(Button.ClickEvent event) {
                openModal(new AdminNewQuestion(view));
            }
        });
        addQuestionButton.setIcon(Config.ICON_ADD);

        addQuestionWrap.addComponent(addQuestionButton);
        return addQuestionWrap;
    }
    
    public void updateQuestionSelect() {
        
        // only show table when there are contents for it
        if(getDomainsTableContainer().size() == 0) {
            domainTable.setVisible(false);
            noDomainsBox.setVisible(true);
        } else {
            domainTable.setVisible(true);
            noDomainsBox.setVisible(false);
        }
        
        // domain select for questions
        questionSelect.removeAllComponents();
        questionSelect.addComponent(displayForm());
        
        if(getDomainsTableContainer().size() == 0) {
            editQuestionsWrap.setVisible(false);
        } else {
            editQuestionsWrap.setVisible(true);
            p2.removeAllComponents();
            p2.setVisible(false);
        }
    }
   
    /**
     * @return the currentDomain
     */
    public Domain getCurrentDomain() {
        return currentDomain;
    }

    /**
     * @return the domainsTableContainer
     */
    public BeanItemContainer<adminDomainTableArgs> getDomainsTableContainer() {
        return domainsTableContainer;
    }

    /**
     * @return the domainSelect
     */
    public NativeSelect getDomainSelect() {
        return domainSelect;
    }
    
    public AdminQuestionnaire getController() {
        return controller;
    }

	@Override
	public void reBuild() {
		// TODO Auto-generated method stub
		
	}
    
}
